package com.ibeeking.found.upms.b.rest.service.impl;

import com.ibeeking.found.upms.b.rest.service.ICsRoleService;
import com.ibeeking.found.upms.b.rest.service.ICsUserRoleService;
import com.ibeeking.found.upms.b.rest.service.ICsUserService;
import com.ibeeking.found.common.entity.CurrentUser;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.upms.service.common.bo.CsUserBO;
import com.ibeeking.found.upms.service.common.bo.CsUserRoleBO;
import com.ibeeking.found.upms.service.common.dos.CsUserRoleDO;
import com.ibeeking.found.upms.service.common.param.RoleUserParam;
import com.ibeeking.found.upms.service.common.param.UserRoleParam;
import com.ibeeking.found.upms.service.mapper.CsUserRoleMapper;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName CsUserRoleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-05-10 9:54
 **/
@Service
public class CsUserRoleServiceImpl implements ICsUserRoleService {

    @Resource
    private CsUserRoleMapper csUserRoleMapper;
    @Resource
    private ICsRoleService csRoleServiceImpl;
    @Resource
    private ICsUserService csUserServiceImpl;

    @Transactional(rollbackFor = {BusinessException.class})
    @Override
    public Boolean modifyUserRoleByUserId(CurrentUser currentUser, UserRoleParam param) {
        if (currentUser.getId().equals(param.getUserId())) {
            throw new BusinessException("禁止修改自己的角色");
        }
        CsUserBO csUserBO = csUserServiceImpl.queryById(param.getUserId());
        if (PublishStatusEnum.DISABLE.getValue().equals(csUserBO.getPublishStatus()) || PublishStatusEnum.DISABLE.getValue().equals(csUserBO.getJob())) {
            throw new BusinessException("用户已离职或被锁定，禁止配置角色");
        }
        //查询管理员
        Long administratorId = csRoleServiceImpl.selectAdministratorId();
        List<Long> userIds = queryUserIdsByRoleId(administratorId).stream().map(CsUserRoleBO::getUserId).collect(Collectors.toList());

        csUserRoleMapper.delete(new LambdaQueryWrapper<>(CsUserRoleDO.class)
                .eq(CsUserRoleDO::getUserId, param.getUserId()));

        // 1. 查询现有用户角色id列表
        List<CsUserRoleBO> csUserRoleBos = queryRoleIdsByUserId(currentUser.getId());
        List<Long> haveRoleIds = csUserRoleBos.stream().map(CsUserRoleBO::getRoleId).collect(Collectors.toList());
        if (null == param.getRoleIds() || 0 == param.getRoleIds().length) {
            if (haveRoleIds.contains(administratorId)) {
                throw new BusinessException("超级管理员至少要有1个用户");
            }
            return true;
        }
        List<Long> paramIds = Arrays.asList(param.getRoleIds());
        if (paramIds.contains(administratorId) && 0 != userIds.size() && !userIds.contains(currentUser.getId())) {
            throw new BusinessException("超级管理员至多只能有1个用户");
        }
        //新增关系
        List<CsUserRoleDO> saves = new ArrayList<>();
        paramIds.stream().forEach(key -> {
            CsUserRoleDO userRoleDO = new CsUserRoleDO();
            userRoleDO.setRoleId(key);
            userRoleDO.setUserId(param.getUserId());

            saves.add(userRoleDO);
        });
        // 新增关系
        csUserRoleMapper.insertBatchSomeColumn(saves);
        return true;
    }

    @Override
    public List<CsUserRoleBO> queryRoleIdsByUserId(Long userId) {
        List<CsUserRoleDO> userRoleDoS = csUserRoleMapper.selectList(new LambdaQueryWrapper<>(CsUserRoleDO.class).eq(CsUserRoleDO::getUserId, userId));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CsUserRoleBO.class);
    }

    @Transactional(rollbackFor = {BusinessException.class})
    @Override
    public Boolean modifyUserRoleByRoleId(CurrentUser currentUser, RoleUserParam param) {
        csUserRoleMapper.delete(new LambdaQueryWrapper<>(CsUserRoleDO.class)
                .eq(CsUserRoleDO::getRoleId, param.getRoleId()));

        Long administratorId = csRoleServiceImpl.selectAdministratorId();
        if (null == param.getUserIds() || 0 == param.getUserIds().length) {
            if (param.getRoleId().equals(administratorId)) {
                throw new BusinessException("超级管理员至少选择一个用户");
            }
            return true;
        }
        List<Long> paramIds = Arrays.asList(param.getUserIds());
        if (param.getRoleId().equals(administratorId) && paramIds.size() > 1) {
            throw new BusinessException("超级管理员至多选择一个用户");
        }
        //新增关系
        List<CsUserRoleDO> saves = new ArrayList<>();
        paramIds.parallelStream().forEach(key -> {
            CsUserRoleDO userRoleDO = new CsUserRoleDO();
            userRoleDO.setRoleId(param.getRoleId());
            userRoleDO.setUserId(key);

            saves.add(userRoleDO);
        });
        csUserRoleMapper.insertBatchSomeColumn(saves);
        return true;
    }

    @Override
    public List<CsUserRoleBO> queryUserIdsByRoleId(Long roleId) {
        List<CsUserRoleDO> userRoleDoS = csUserRoleMapper.selectList(new LambdaQueryWrapper<>(CsUserRoleDO.class).eq(CsUserRoleDO::getRoleId, roleId));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CsUserRoleBO.class);
    }

    @Override
    public Boolean delByUserId(Long userId) {
        return csUserRoleMapper.delete(new LambdaUpdateWrapper<>(CsUserRoleDO.class).eq(CsUserRoleDO::getUserId, userId)) > 0;
    }

    @Override
    public Boolean delByRoleId(Long roleId) {
        return csUserRoleMapper.delete(new LambdaUpdateWrapper<>(CsUserRoleDO.class).eq(CsUserRoleDO::getRoleId, roleId)) > 0;
    }

    @Override
    public List<CsUserRoleBO> queryRoleIdsByUserIds(List<Long> userIds) {
        List<CsUserRoleDO> userRoleDoS = csUserRoleMapper.selectList(new LambdaQueryWrapper<>(CsUserRoleDO.class).in(CsUserRoleDO::getUserId, userIds));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CsUserRoleBO.class);
    }

    @Override
    public List<CsUserRoleBO> queryUserIdsByRoleIds(List<Long> roleIds) {
        List<CsUserRoleDO> userRoleDoS = csUserRoleMapper.selectList(new LambdaQueryWrapper<>(CsUserRoleDO.class).in(CsUserRoleDO::getRoleId, roleIds));
        if (Collections3.isEmpty(userRoleDoS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(userRoleDoS, CsUserRoleBO.class);
    }
}
